<?php
//
//	file: includes/attach/class_file_handler_ftp.php
//	author: ptirhiik
//	begin: 05/03/2006
//	version: 1.6.3 - 09/02/2007
//	license: http://opensource.org/licenses/gpl-license.php GNU General Public License (GPL)
//
//	based on : attachment_mod copyright (c) 2002 Meik Sievertsen (acydburn)
//

if ( !defined('IN_PHPBB') )
{
	die('Hacking attempt');
	exit;
}

// timeout for ftp connection in second : sys default is 90s
// note this parameter has been added in php 4.2.0
define('FTP_CONNECT_TIMEOUT', 28);

class file_handler_ftp
{
	var $root_path;

	var $download_path;
	var $download_private;

	var $server;
	var $port;
	var $user;
	var $pass;
	var $pasv;
	var $conn_id;
	var $error;
	var $error_parm;

	var $safe_mode;
	var $temporary_file;

	function file_handler_ftp($ftp_root_path, $ftp_download_path, $ftp_server, $ftp_port, $ftp_user, $ftp_pass, $ftp_pasv)
	{
		$this->root_path = '';
		$this->root_path = $this->path($ftp_root_path);

		// download
		$ftp_download_path = trim(preg_replace('#(.*)?\/?$#', '\1', trim($ftp_download_path)));
		$this->download_path = $ftp_download_path;
		$this->download_private = !empty($ftp_download_path);

		$this->server = trim($ftp_server) == '' ? 'localhost' : trim($ftp_server);
		$this->port = intval($ftp_port) ? intval($ftp_port) : 21;
		$this->user = $ftp_user;
		$this->pass = $ftp_pass;
		$this->pasv = $ftp_pasv;
		$this->conn_id = false;
		$this->error = '';
		$this->error_parm = '';

		$this->temporary_file = false;
		$this->safe_mode = @ini_get('safe_mode');
	}

	function check_settings($ftp_dir)
	{
		$this->error = $this->error_parm = '';
		$this->open_channel();
		if ( !$this->error )
		{
			// create a local file
			$check_file = '0_000000.000';
			$mimetype = 'text';
			$tmp_file = tempnam($this->safe_mode ? $this->root_path : TMP_PATH, $check_file);
			@unlink($tmp_file); // unlink for safety on php4.0.3+
			$fp = @fopen($tmp_file, 'w');
			@fwrite($fp, 'test');
			@fclose($fp);

			// attempt to upload it
			$dst_file = $this->path((empty($ftp_dir) ? '' : $ftp_dir . '/') . $check_file);
			$result = $this->upload($tmp_file, $mimetype, $dst_file);
			if ( $result )
			{
				$this->delete($dst_file);
			}
			$this->close_channel();
			@unlink($tmp_file);
		}
		return !$this->error;
	}

	function get_download_url($src_file)
	{
		return $this->download_private ? false : $this->download_path . '/' . $src_file;
	}

	function path($ftp_dir)
	{
		$ftp_dir = empty($ftp_dir) ? '' : trim(preg_replace('#^\/?(.*?)\/?$#', '\1', $ftp_dir));
		return $this->root_path . (empty($this->root_path) || empty($ftp_dir) ? '' : '/') . $ftp_dir;
	}

	function open_channel()
	{
		if ( $this->conn_id )
		{
			$this->close_channel;
		}
		$this->error = $this->error_parm = '';

		if ( !($this->conn_id = @ftp_connect($this->server, $this->port, FTP_CONNECT_TIMEOUT)) )
		{
			$this->error = 'Ftp_error_connect';
			$this->error_parm = $this->server;
			return false;
		}
		if ( !@ftp_login($this->conn_id, $this->user, $this->pass) )
		{
			$this->close_channel();
			$this->error = 'Ftp_error_login';
			$this->error_parm = $this->user;
			return false;
		}
		if ( !@ftp_pasv($this->conn_id, $this->pasv) )
		{
			$this->close_channel();
			$this->error = 'Ftp_error_pasv_mode';
			$this->error_parm = $this->pasv;
			return false;
		}
		if ( !empty($this->root_path) && !@ftp_chdir($this->conn_id, $this->root_path) )
		{
			$this->close_channel();
			$this->error = 'Ftp_error_path';
			$this->error_parm = $this->root_path;
			return false;
		}
		return true;
	}

	function close_channel($silent=false)
	{
		if ( !$silent )
		{
			$this->error = $this->error_parm = '';
		}
		if ( !$this->conn_id )
		{
			return true;
		}
		@ftp_quit($this->conn_id);
		$this->conn_id = false;
		if ( !$silent )
		{
			$this->error = $this->error_parm = '';
		}
		return true;
	}

	function read_channel($ftp_dir, &$files, $file_prefix='')
	{
		$files = array();
		$this->error = $this->error_parm = '';
		if ( !$this->conn_id )
		{
			$this->error = 'Ftp_error_not_connected';
			return false;
		}
		if ( !empty($ftp_dir) )
		{
			$ftp_dir = $this->path($ftp_dir);
			@ftp_chdir($this->conn_id, '/' . $ftp_dir);
		}
		$prefix = empty($file_prefix) ? '' : trim($file_prefix);
		$prefix_len = empty($prefix) ? 0 : strlen($prefix);

		$file_listing = array();
		$file_listening = @ftp_rawlist($this->conn_id, '');
		$count_file_listing = count($file_listing);
		for ( $i = 0; $i < $count_file_listing; $i++ )
		{
			if ( ereg('([-d])[rwxst-]{9}.* ([0-9]*) ([a-zA-Z]+[0-9: ]*[0-9]) ([0-9]{2}:[0-9]{2}) (.+)', $file_listing[$i], $regs) )
			{
				// don't retain directories
				if ( $regs[1] != 'd' )
				{
					$filename = trim($regs[4]);
					if ( !empty($filename) && !in_array($filename, array('index.php', 'index.html', '.htaccess')) )
					{
						$filename = $prefix_len && (substr($filename, 0, $prefix_len) == $prefix) ? trim(substr($filename, $prefix_len)) : $filename;
						if ( !empty($filename) )
						{
							$files[] = $filename;
						}
					}
				}
			}
			unset($file_listing[$i]);
		}
	}

	function upload($src_file, $mimetype, $dst_file)
	{
		$this->error = $this->error_parm = '';
		if ( !$this->conn_id )
		{
			$this->error = 'Ftp_error_not_connected';
			return false;
		}
		if ( !is_uploaded_file($src_file) )
		{
			$this->error = 'Ftp_error_no_srcfile';
			return false;
		}

		// Binary or Ascii ?
		$src_file = phpbb_realpath($src_file);
		$dst_path = dirname($dst_file);
		$dst_file = basename($dst_file);
		if ( !@ftp_chdir($this->conn_id, '/' . $dst_path) )
		{
			$this->error = 'Ftp_error_path';
			$this->error_parm = $dst_path;
			return false;
		}
		if ( !@ftp_put($this->conn_id, $dst_file, $src_file, preg_match('/(text|html)/i', $mimetype) ? FTP_ASCII : FTP_BINARY) )
		{
			$this->error = 'Ftp_error_upload';
			$this->error_parm = $dst_path;
			return false;
		}
		$this->chmod($dst_file);
		return true;
	}

	function chmod($dst_file)
	{
		$this->error = $this->error_parm = '';
		if ( !$this->conn_id )
		{
			$this->error = 'Ftp_error_not_connected';
			return false;
		}
		@ftp_site($this->conn_id, 'CHMOD 0644 ' . $dst_file);
		return true;
	}

	function delete($src_file)
	{
		$this->error = $this->error_parm = '';
		if ( !$this->conn_id )
		{
			$this->error = 'Ftp_error_not_connected';
			return false;
		}
		$src_path = dirname($src_file);
		$src_file = basename($src_file);
		if ( !@ftp_chdir($this->conn_id, '/' . $src_path) )
		{
			$this->error = 'Ftp_error_upload';
			$this->error_parm = $src_path;
			return false;
		}
		if ( !@ftp_delete($this->conn_id, $src_file) )
		{
			$this->error = 'Ftp_error_delete';
			$this->error_parm = dirname($src_file);
			return false;
		}
		return true;
	}

	function get_temporary_filename($src_file='', $dst_file='')
	{
		$this->error = $this->error_parm = '';
		$tmp_file = tempnam($this->safe_mode ? $this->root_path : TMP_PATH, 't00000');
		if ( empty($tmp_file) )
		{
			$this->error = 'Ftp_error_no_tmpfile';
			return false;
		}
		@unlink($tmp_file);
		return $tmp_file;
	}

	function get_filesize($filename)
	{
		$this->error = $this->error_parm = '';
		if ( !$this->conn_id )
		{
			$this->error = 'Ftp_error_not_connected';
			return false;
		}
		$result = @ftp_size($filename);
		return ($result == -1) ? false : intval($result);
	}

	function get_temporary($src_file, $mimetype)
	{
		$this->temporary_file = false;

		// the path is public, so just return it formatted
		if ( !$this->download_private && @file_exists($src_file) )
		{
			return $src_file;
		}

		// the path is private : we need to get the file localy
		$this->error = $this->error_parm = '';
		if ( !$this->open_channel() )
		{
			return false;
		}
		if ( !($tmp_file = $this->get_temporary_filename()) )
		{
			$this->close_channel();
			return false;
		}
		$src_path = dirname($src_file);
		$src_file = basename($src_file);
		if ( !@ftp_chdir($this->conn_id, '/' . $src_path) )
		{
			$this->error = 'Ftp_error_upload';
			$this->error_parm = $src_path;
			return false;
		}
		if ( !($result = @ftp_get($this->conn_id, $tmp_file, $src_file, preg_match('/(text|html)/i', $mimetype) ? FTP_ASCII : FTP_BINARY)) )
		{
			$this->error = 'Error_no_attachment';
		}
		else
		{
			$this->temporary_file = true;
		}
		$this->close_channel();
		return $result ? $tmp_file : false;
	}

	function unlink_temporary($tmp_file)
	{
		if ( $this->temporary_file && $tmp_file )
		{
			@unlink($tmp_file);
		}
		return true;
	}
}

?>